package com.example.aigc_education.aop;
import java.lang.reflect.Method;
import com.example.aigc_education.anno.RequestLock;
import com.example.aigc_education.exception.RequestRepeatException;
import com.example.aigc_education.utils.RedisCache;
import com.example.aigc_education.utils.RequestKeyGenerator;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

/**
 * @description 缓存实现
 */
@Aspect
@Configuration
@Order(2)
public class RedisRequestLockAspect {



    @Resource
    private RedisCache redisCache;

    @Around("@annotation(com.example.aigc_education.anno.RequestLock)")
    public Object interceptor(ProceedingJoinPoint joinPoint) throws Throwable {


        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        RequestLock requestLock = method.getAnnotation(RequestLock.class);
        if (StringUtils.isEmpty(requestLock.prefix())) {
            throw new RequestRepeatException("重复提交前缀不能为空");
        }
        //获取自定义key
        final String lockKey = RequestKeyGenerator.getLockKey(joinPoint);
        // 使用RedisCallback接口执行set命令，设置锁键；设置额外选项：过期时间和SET_IF_ABSENT选项
        final Boolean success = redisCache.setCacheObjectAndJudge(lockKey,"keyValue",requestLock.expire(),requestLock.timeUnit());
        if (!success) {
            throw new RequestRepeatException("您的操作太快了,请稍后重试");
        }
        return joinPoint.proceed();
    }
}